package com.seo.utils;

import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Map;

import javax.imageio.ImageIO;
import javax.imageio.stream.ImageOutputStream;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.NotFoundException;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;

import cn.hutool.core.codec.Base64Encoder;

/**
 * 二维码
 * 创建人：administrator
 * 创建时间：2018.08.02 17:40
 */
public class TwoDimensionCode {

    /**
     * 生成二维码(QRCode)图片
     *
     * @param content 存储内容
     * @param imgPath 图片路径
     */
    public static void encoderQRCode(String content, String imgPath) {
        encoderQRCode(content, imgPath, "png", 2);
    }

    /**
     * 生成二维码(QRCode)图片
     *
     * @param content 存储内容
     * @param output  输出流
     */
    public static void encoderQRCode(String content, OutputStream output) {
        encoderQRCode(content, output, "png", 2);
    }

    /**
     * 生成二维码(QRCode)图片
     *
     * @param content 存储内容
     * @param imgPath 图片路径
     * @param imgType 图片类型
     */
    public static InputStream encoderQRCode(String content, String imgPath, String imgType) {
        InputStream is = encodeZXcode(content, imgType);
        return is;
    }

    /**
     * 生成二维码(QRCode)图片
     *
     * @param content 存储内容
     * @param output  输出流
     * @param imgType 图片类型
     */
    public static void encoderQRCode(String content, OutputStream output, String imgType) {
        encoderQRCode(content, output, imgType, 2);
    }

    /**
     * 生成二维码(QRCode)图片
     *
     * @param content 存储内容
     * @param imgPath 图片路径
     * @param imgType 图片类型
     * @param size    二维码尺寸
     */
    public static void encoderQRCode(String content, String imgPath, String imgType, int size) {
        try {
            BufferedImage bufImg = qRCodeCommon(content, imgType, size);

            File imgFile = new File(imgPath);
            // 生成二维码QRCode图片
            ImageIO.write(bufImg, imgType, imgFile);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static InputStream encoderQRCode(String content, String imgType, int size) {
        try {
            ByteArrayOutputStream bs = new ByteArrayOutputStream();
            ImageOutputStream imOut = ImageIO.createImageOutputStream(bs);
            BufferedImage bufImg = qRCodeCommon(content, imgType, size);
            // 生成二维码QRCode图片
            ImageIO.write(bufImg, imgType, imOut);
            InputStream is = new ByteArrayInputStream(bs.toByteArray());
            return is;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    public static InputStream encodeZXcode(String url, String imgType) {
        try {
            ByteArrayOutputStream bs = new ByteArrayOutputStream();
            ImageOutputStream imOut = ImageIO.createImageOutputStream(bs);
            BufferedImage bufImg = encodeZXcode(url);
            // 生成二维码QRCode图片
            ImageIO.write(bufImg, imgType, imOut);
            InputStream is = new ByteArrayInputStream(bs.toByteArray());
            return is;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 生成二维码(QRCode)图片
     *
     * @param content 存储内容
     * @param output  输出流
     * @param imgType 图片类型
     * @param size    二维码尺寸
     */
    public static void encoderQRCode(String content, OutputStream output, String imgType,
                                     int size) {
        try {
            BufferedImage bufImg = qRCodeCommon(content, imgType, size);
            // 生成二维码QRCode图片
            ImageIO.write(bufImg, imgType, output);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 生成二维码(QRCode)图片的公共方法
     *
     * @param content 存储内容
     * @param imgType 图片类型
     * @param size    二维码尺寸
     * @return
     */
    private static BufferedImage qRCodeCommon(String content, String imgType, int size) {
        size = 4;
        int imgSize = 150 + 10 * (size - 1);
        try {
            return IQRCode.createImg(content, imgSize, imgSize);
        } catch (IOException e) {
            return null;
        }
    }

    private static BufferedImage encodeZXcode(String url) {
        try {
            MultiFormatWriter multiFormatWriter = new MultiFormatWriter();
            Map<EncodeHintType, Object> hints = new HashMap<>();
            hints.put(EncodeHintType.CHARACTER_SET, "UTF-8"); // 设置字符集编码类型
            hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);
            hints.put(EncodeHintType.MARGIN, 0);
            BitMatrix bitMatrix = null;

            bitMatrix = multiFormatWriter.encode(url, BarcodeFormat.QR_CODE, 300, 300, hints);
            BufferedImage image = toBufferedImage(bitMatrix);
            // 输出二维码图片流
            return image;
        } catch (WriterException e1) {
            e1.printStackTrace();
            return null;
        }
    }

    private static BufferedImage toBufferedImage(BitMatrix matrix) {
        int WHITE = 0xFFFFFFFF;
        int BLACK = 0xFF000000;
        int width = matrix.getWidth();
        int height = matrix.getHeight();
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        for (int x = 0; x < width; x++) {
            for (int y = 0; y < height; y++) {
                image.setRGB(x, y, matrix.get(x, y) ? BLACK : WHITE);
            }
        }
        return image;
    }

    /**
     * 解析二维码（QRCode）
     *
     * @param imgPath 图片路径
     * @return
     */
    public static String decoderQRCode(String imgPath) throws Exception {
        // QRCode 二维码图片的文件
        return IQRCode.read(imgPath);
    }

    /**
     * 解析二维码（QRCode）
     *
     * @param input 输入流
     * @return
     */
    public static String decoderQRCode(InputStream input) throws IOException, NotFoundException {
        return IQRCode.read(input);
    }
    
    /**
     * 生成二维码(QRCode)图片 转 base64
     *
     * @param content 存储内容
     */
    public static String encoderQRCodeToBase64(String content) {
        String base64Img = null;
        try {
            BufferedImage bufImg = qRCodeCommon(content, "png", 2);
            // bufferImage->base64
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            ImageIO.write(bufImg, "png", outputStream);
            Base64Encoder encoder = new Base64Encoder();
            base64Img = encoder.encode(outputStream.toByteArray());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return base64Img;
    }
}
